import sys
import os
from datetime import datetime
from PyQt5.QtWidgets import (QApplication, QMainWindow, QVBoxLayout, QHBoxLayout, QWidget, QPushButton, QLineEdit,
                             QLabel, QFileDialog, QHeaderView, QDialog, QTextEdit, QMessageBox, QTableView,
                             QAbstractItemView, QCheckBox, QComboBox)
from PyQt5.QtCore import Qt, QAbstractTableModel, QModelIndex, QVariant
from PyQt5.QtGui import QColor, QPalette, QIcon, QFont
from kubernetes import client, config
from kubernetes.client import ApiClient
from kubernetes.stream import stream
import qdarkstyle
import urllib3

# 禁用 urllib3 的 InsecureRequestWarning
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

class PodTableModel(QAbstractTableModel):
    def __init__(self, data=None):
        super().__init__()
        self._data = data or []
        self._headers = ["Namespace", "Name", "Status", "Restarts", "Age", "Actions"]

    def data(self, index, role):
        if role == Qt.DisplayRole:
            return self._data[index.row()][index.column()]
        elif role == Qt.TextAlignmentRole:
            return Qt.AlignCenter
        elif role == Qt.BackgroundRole:
            if index.row() % 2 == 0:
                return QColor(53, 53, 53)  # 调整为更深的条纹颜色
        elif role == Qt.FontRole:
            font = QFont()
            if index.column() == 2:  # Status 列
                font.setBold(True)
            return font
        return QVariant()

    def rowCount(self, index):
        return len(self._data)

    def columnCount(self, index):
        return len(self._headers)

    def headerData(self, section, orientation, role):
        if role == Qt.DisplayRole and orientation == Qt.Horizontal:
            return self._headers[section]
        return QVariant()

    def setData(self, data):
        self.beginResetModel()
        self._data = data
        self.endResetModel()
class FileTableModel(QAbstractTableModel):
    def __init__(self, data=None):
        super().__init__()
        self._data = data or []
        self._headers = ["名称", "路径", "类型", "大小", "创建时间", "修改时间", "操作"]

    def data(self, index, role):
        if role == Qt.DisplayRole:
            return self._data[index.row()][index.column()]
        elif role == Qt.TextAlignmentRole:
            return Qt.AlignCenter
        elif role == Qt.BackgroundRole:
            if index.row() % 2 == 0:
                return QColor(53, 53, 53)  # 调整为更深的条纹颜色
        elif role == Qt.FontRole:
            font = QFont()
            if index.column() == 2:  # Type 列
                font.setBold(True)
            return font
        return QVariant()

    def rowCount(self, index):
        return len(self._data)

    def columnCount(self, index):
        return len(self._headers)

    def headerData(self, section, orientation, role):
        if role == Qt.DisplayRole and orientation == Qt.Horizontal:
            return self._headers[section]
        return QVariant()

    def setData(self, data):
        self.beginResetModel()
        self._data = data
        self.endResetModel()


class PodConnectionDialog(QDialog):
    def __init__(self, api_client, namespace, pod_name):
        super().__init__()
        self.api_client = api_client
        self.namespace = namespace
        self.pod_name = pod_name
        self.current_path = "/"
        self.init_ui()
        self.auto_connect()

    def init_ui(self):
        self.setWindowTitle(f"已连接到 {self.pod_name}")
        self.setGeometry(200, 200, 800, 600)

        layout = QVBoxLayout()

        self.path_label = QLabel()
        self.path_label.setAlignment(Qt.AlignLeft)
        self.update_path_label()
        layout.addWidget(self.path_label)

        self.file_model = FileTableModel()
        self.file_table = QTableView()
        self.file_table.setModel(self.file_model)
        self.file_table.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.file_table.setSelectionMode(QAbstractItemView.SingleSelection)
        self.file_table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        self.file_table.verticalHeader().setVisible(False)
        self.file_table.clicked.connect(self.handle_table_click)
        layout.addWidget(self.file_table)

        self.setLayout(layout)

    def auto_connect(self):
        # 默认尝试连接至 Pod 并列出根目录下的文件
        self.list_directory(self.current_path)

    def update_path_label(self):
        path_parts = self.current_path.strip('/').split('/')
        path_links = []
        full_path = ""
        for part in path_parts:
            full_path += '/' + part
            path_link = f"<a href='{full_path}'>{part}</a>"
            path_links.append(path_link)
        path_label_text = "当前路径: <a href='/'>/</a> " + " / ".join(path_links)
        self.path_label.setText(path_label_text)
        self.path_label.linkActivated.connect(self.handle_path_link)

    def handle_path_link(self, link):
        self.list_directory(link)

    def list_directory(self, path):
        self.current_path = path if path.endswith('/') else path + '/'
        v1 = client.CoreV1Api(self.api_client)
        exec_command = ['/bin/sh', '-c', f'ls -l --full-time {path}']

        try:
            resp = stream(v1.connect_get_namespaced_pod_exec,
                          self.pod_name,
                          self.namespace,
                          command=exec_command,
                          stderr=True, stdin=False,
                          stdout=True, tty=False)
            self.parse_ls_output(resp)
        except Exception as e:
            QMessageBox.critical(self, "错误", f"列出目录时出错：{str(e)}")
            self.close()  # 关闭弹窗

    def parse_ls_output(self, output):
        lines = output.strip().split('\n')
        file_data = []

        for line in lines:
            parts = line.split(maxsplit=8)
            if len(parts) < 9:
                continue
            permissions, _, _, _, size, creation_time, modification_time, _, name = parts
            file_type = '文件夹' if permissions.startswith('d') else '文件'
            action = '进入' if file_type == '文件夹' else '查看'
            file_data.append(
                [name, self.current_path, file_type, size, creation_time, modification_time, action])

        self.file_model.setData(file_data)
        self.update_path_label()

    def handle_table_click(self, index):
        column = index.column()
        row = index.row()
        if column == 6:  # 假设 '操作' 列的 '查看' 在索引 6
            file_type = self.file_model._data[row][2]
            file_path = self.file_model._data[row][1] + self.file_model._data[row][0]
            if file_type == '文件夹':
                self.list_directory(file_path)
            else:
                self.view_file_content(file_path)

    def view_file_content(self, file_path):
        v1 = client.CoreV1Api(self.api_client)
        exec_command = ['/bin/sh', '-c', f'cat {file_path}']

        try:
            resp = stream(v1.connect_get_namespaced_pod_exec,
                          self.pod_name,
                          self.namespace,
                          command=exec_command,
                          stderr=True, stdin=False,
                          stdout=True, tty=False)
            self.show_file_content_dialog(file_path, resp)
        except Exception as e:
            QMessageBox.critical(self, "错误", f"查看文件内容时出错：{str(e)}")

    def show_file_content_dialog(self, file_path, content):
        dialog = QDialog(self)
        dialog.setWindowTitle(f"文件内容：{file_path}")
        dialog.setGeometry(200, 200, 800, 600)

        layout = QVBoxLayout()

        text_edit = QTextEdit()
        text_edit.setReadOnly(True)
        text_edit.setText(content)
        layout.addWidget(text_edit)

        dialog.setLayout(layout)
        dialog.exec_()


class K8sPodManager(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("K8s Pod 管理器")
        self.setGeometry(100, 100, 1200, 600)

        self.central_widget = QWidget()
        self.setCentralWidget(self.central_widget)
        self.layout = QVBoxLayout(self.central_widget)

        self.kubeconfig_path = None
        self.cert_path = None
        self.key_path = None
        self.api_client = None

        self.init_ui()

    def init_ui(self):
        # 连接设置
        connection_layout = QHBoxLayout()

        # 连接方法下拉框
        self.connection_method = QComboBox()
        self.connection_method.addItems(["Kubeconfig 文件", "客户端证书和密钥", "Token"])
        self.connection_method.currentIndexChanged.connect(self.update_connection_ui)
        connection_layout.addWidget(self.connection_method)

        # Kubeconfig 文件选择
        self.kubeconfig_button = QPushButton("选择 Kubeconfig")
        self.kubeconfig_button.clicked.connect(lambda: self.select_file('kubeconfig'))
        connection_layout.addWidget(self.kubeconfig_button)

        # 证书和密钥选择
        self.api_server_input = QLineEdit()
        self.api_server_input.setPlaceholderText("K8s API 服务器地址")
        self.cert_button = QPushButton("选择crt文件")
        self.key_button = QPushButton("选择key文件")
        connection_layout.addWidget(self.api_server_input,3)
        connection_layout.addWidget(self.cert_button,1)
        connection_layout.addWidget(self.key_button,1)

        # Token 连接
        self.token_host_input = QLineEdit()
        self.token_host_input.setPlaceholderText("K8s API 服务器地址")
        self.token_input = QLineEdit()
        self.token_input.setPlaceholderText("API Token")
        self.verify_ssl_checkbox = QCheckBox("验证 SSL")
        connection_layout.addWidget(self.token_host_input)
        connection_layout.addWidget(self.token_input)
        connection_layout.addWidget(self.verify_ssl_checkbox)

        # 连接按钮
        self.connect_button = QPushButton("连接")
        self.connect_button.setMinimumSize(130, 0)
        connection_layout.addWidget(self.connect_button)

        self.layout.addLayout(connection_layout)

        # Pod 表格
        self.pod_model = PodTableModel()
        self.pod_table = QTableView()
        self.pod_table.setModel(self.pod_model)
        self.pod_table.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.pod_table.setSelectionMode(QAbstractItemView.SingleSelection)
        self.pod_table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        self.pod_table.verticalHeader().setVisible(False)
        self.layout.addWidget(self.pod_table)

        # Pod 操作
        action_layout = QHBoxLayout()
        self.refresh_button = QPushButton("刷新")
        self.filter_button = QPushButton("筛选")
        action_layout.addWidget(self.refresh_button)
        action_layout.addWidget(self.filter_button)
        self.layout.addLayout(action_layout)

        # 连接信号
        self.cert_button.clicked.connect(lambda: self.select_file('cert'))
        self.key_button.clicked.connect(lambda: self.select_file('key'))
        self.connect_button.clicked.connect(self.connect_to_cluster)
        self.refresh_button.clicked.connect(lambda: self.refresh_pods())
        self.filter_button.clicked.connect(self.open_filter_dialog)
        self.pod_table.clicked.connect(self.handle_table_click)

        self.apply_styles()
        self.update_connection_ui(0)  # 初始化 UI 为 Kubeconfig 方法

    def apply_styles(self):
        self.setStyleSheet(qdarkstyle.load_stylesheet_pyqt5())

    def update_connection_ui(self, index):
        # 隐藏所有控件
        self.kubeconfig_button.hide()
        self.api_server_input.hide()
        self.cert_button.hide()
        self.key_button.hide()
        self.token_host_input.hide()
        self.token_input.hide()
        self.verify_ssl_checkbox.hide()

        # 根据选择的方法显示相关控件
        if index == 0:  # Kubeconfig 文件
            self.kubeconfig_button.show()
        elif index == 1:  # 客户端证书和密钥
            self.api_server_input.show()
            self.cert_button.show()
            self.key_button.show()
        elif index == 2:  # Token
            self.token_host_input.show()
            self.token_input.show()
            self.verify_ssl_checkbox.show()

    def select_file(self, file_type):
        if file_type == 'kubeconfig':
            file_path, _ = QFileDialog.getOpenFileName(self, "选择 Kubeconfig 文件")
            if file_path:
                self.kubeconfig_path = file_path
                self.kubeconfig_button.setText("已选择 Kubeconfig")
        elif file_type == 'cert':
            file_path, _ = QFileDialog.getOpenFileName(self, "选择crt文件")
            if file_path:
                self.cert_path = file_path
                self.cert_button.setText("已选择crt文件")
        elif file_type == 'key':
            file_path, _ = QFileDialog.getOpenFileName(self, "选择key文件")
            if file_path:
                self.key_path = file_path
                self.key_button.setText("已选择key文件")

    def connect_to_cluster(self):
        connection_method = self.connection_method.currentIndex()

        try:
            if connection_method == 0:  # Kubeconfig 文件
                if not self.kubeconfig_path:
                    raise ValueError("请选择 Kubeconfig 文件。")
                config.load_kube_config(config_file=self.kubeconfig_path)
                self.api_client = client.ApiClient()

            elif connection_method == 1:  # 客户端证书和密钥
                api_server = self.api_server_input.text()
                if not api_server or not self.cert_path or not self.key_path:
                    raise ValueError("请输入 API 服务器地址并选择证书和密钥文件。")
                configuration = client.Configuration()
                configuration.host = api_server
                configuration.cert_file = self.cert_path
                configuration.key_file = self.key_path
                configuration.verify_ssl = False  # 注意：在生产环境中，您应该验证 SSL
                self.api_client = ApiClient(configuration)

            elif connection_method == 2:  # Token
                host = self.token_host_input.text()
                token = self.token_input.text()
                if not host or not token:
                    raise ValueError("请输入 API 服务器地址和 Token。")
                configuration = client.Configuration()
                configuration.host = host
                configuration.api_key = {"authorization": f"Bearer {token}"}
                configuration.verify_ssl = self.verify_ssl_checkbox.isChecked()
                self.api_client = ApiClient(configuration)

            self.refresh_pods()
            QMessageBox.information(self, "连接成功", "成功连接到 Kubernetes 集群。")
            # print("Connection successful with method:", connection_method)
        except Exception as e:
            QMessageBox.critical(self, "连接错误", f"连接到 Kubernetes 集群失败：{str(e)}")
            # print("Connection failed:", str(e))

    def refresh_pods(self, filter_namespaces=None):
        if not self.api_client:
            QMessageBox.warning(self, "未连接", "请先连接到 Kubernetes 集群。")
            return
        try:
            v1 = client.CoreV1Api(self.api_client)
            pods = v1.list_pod_for_all_namespaces()
            pod_data = []
            # print(filter_namespaces)
            for pod in pods.items:
                if filter_namespaces is None or pod.metadata.namespace in filter_namespaces:
                    namespace = pod.metadata.namespace
                    name = pod.metadata.name
                    status = pod.status.phase
                    restart_count = pod.status.container_statuses[
                        0].restart_count if pod.status.container_statuses else 0
                    creation_time = pod.metadata.creation_timestamp
                    age = datetime.now(creation_time.tzinfo) - creation_time
                    age_str = f"{age.days}d {age.seconds // 3600}h {(age.seconds % 3600) // 60}m"

                    pod_data.append([namespace, name, status, str(restart_count), age_str, "连接"])

            self.pod_model.setData(pod_data)
            self.pod_table.resizeColumnsToContents()
        except Exception as e:
            QMessageBox.critical(self, "错误", f"刷新 Pod 失败：{str(e)}")
            # print("Error refreshing pods:", str(e))

    def handle_table_click(self, index):
        column = index.column()
        row = index.row()
        if column == 5:  # 假设 'Actions' 列的 'Connect' 在索引 5
            self.connect_to_pod(row)

    def connect_to_pod(self, row):
        namespace = self.pod_model._data[row][0]
        pod_name = self.pod_model._data[row][1]
        dialog = PodConnectionDialog(self.api_client, namespace, pod_name)
        dialog.exec_()

    def open_filter_dialog(self):
        if not self.api_client:
            QMessageBox.warning(self, "Not Connected", "Please connect to a Kubernetes cluster first.")
            return

        try:
            v1 = client.CoreV1Api(self.api_client)
            namespaces = v1.list_namespace()
            available_namespaces = [ns.metadata.name for ns in namespaces.items]

            dialog = FilterDialog(available_namespaces, self)
            if dialog.exec_():
                selected_namespaces = dialog.get_selected_namespaces()
                self.refresh_pods(selected_namespaces)
        except Exception as e:
            QMessageBox.critical(self, "Error", f"Failed to retrieve namespaces: {str(e)}")


class FilterDialog(QDialog):
    def __init__(self, available_namespaces, parent=None):
        super().__init__(parent)
        self.setWindowTitle("Filter Namespaces")
        self.setGeometry(300, 300, 400, 300)
        self.available_namespaces = available_namespaces
        self.selected_namespaces = available_namespaces.copy()

        # 应用样式表
        self.setStyleSheet("""
                   QDialog {
                       font-size: 14pt;
                       font-family: Arial;
                   }
                   QCheckBox {
                       font-size: 14pt;  /* 单独为多选框设置字体大小 */
                   }
                   QPushButton {
                       font-size: 14pt;  /* 单独为按钮设置字体大小 */
                   }
               """)

        layout = QVBoxLayout(self)

        # 多选框容器
        self.checkbox_layout = QVBoxLayout()
        self.namespace_checkboxes = {}

        for ns in available_namespaces:
            chk = QCheckBox(ns)
            chk.setChecked(True)
            chk.stateChanged.connect(self.update_selection)
            self.namespace_checkboxes[ns] = chk
            self.checkbox_layout.addWidget(chk)

        layout.addLayout(self.checkbox_layout)

        # 确认按钮
        self.confirm_button = QPushButton("Confirm")
        self.confirm_button.clicked.connect(self.accept)
        layout.addWidget(self.confirm_button)

    def update_selection(self):
        self.selected_namespaces = [ns for ns in self.namespace_checkboxes if self.namespace_checkboxes[ns].isChecked()]

    def get_selected_namespaces(self):
        return self.selected_namespaces


if __name__ == '__main__':
    app = QApplication(sys.argv)
    app.setStyleSheet(qdarkstyle.load_stylesheet_pyqt5())
    window = K8sPodManager()
    window.show()
    sys.exit(app.exec_())